﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using ImageProcessingLibrary;

namespace BinocularVision
{
    public class FaceDetection: BrainProcess
    {
        #region Fields
        private ImageProcessor leftWebCamOriginalImage;
        private ImageProcessor rightWebCamOriginalImage;
        
        private ImageProcessor leftWebCamProcessing;
        private ImageProcessor rightWebCamProcessing;

        private ImageProcessor leftWebCamProcessedImage;
        private ImageProcessor rightWebCamProcessedImage;
        private bool faceDetectedPreviously = false;
        #endregion

        #region Public methods
        public override void Step()
        {
            if (CurrentState == 0)
            {
                this.faceDetectedPreviously = false;
                CurrentState = 1;
            }
            else if (CurrentState == 1)
            {
                Bitmap leftImage = Robot.Instance.Body.LeftWebCam.ReadingAsBitmap;
                Bitmap rightImage = Robot.Instance.Body.RightWebCam.ReadingAsBitmap;
                if (leftImage != null && rightImage != null)
                {
                    leftWebCamOriginalImage = new ImageProcessor(leftImage);
                    rightWebCamOriginalImage = new ImageProcessor(rightImage);
                    this.CurrentState = 2;
                }
            }
            else if (CurrentState == 2)
            {
                leftWebCamOriginalImage.Lock();
                rightWebCamOriginalImage.Lock();

                leftWebCamProcessing = leftWebCamOriginalImage.GetSkinPixelsYCbCr();
                rightWebCamProcessing = rightWebCamOriginalImage.GetSkinPixelsYCbCr();

                leftWebCamOriginalImage.UnLock();
                rightWebCamOriginalImage.UnLock();
                this.CurrentState = 3;
            }
            else if (CurrentState == 3)
            {
                leftWebCamProcessing.Lock();
                rightWebCamProcessing.Lock();

                leftWebCamProcessing.RemoveSinglePixels();
                rightWebCamProcessing.RemoveSinglePixels();

                leftWebCamProcessing.UnLock();
                rightWebCamProcessing.UnLock();
                this.CurrentState = 4;
            }
            else if (CurrentState == 4)
            {
                leftWebCamProcessing.Lock();
                rightWebCamProcessing.Lock();

                leftWebCamProcessing.ExtractConnectedComponents();
                rightWebCamProcessing.ExtractConnectedComponents();

                leftWebCamProcessing.RemoveSmallComponents(400);
                rightWebCamProcessing.RemoveSmallComponents(400);

                leftWebCamProcessing.RemoveNonFaces(0.4, 0.9);
                rightWebCamProcessing.RemoveNonFaces(0.4, 0.9);

                leftWebCamOriginalImage.Lock();
                rightWebCamOriginalImage.Lock();

                leftWebCamProcessing.FilterOutConnectedComponents(leftWebCamOriginalImage);
                rightWebCamProcessing.FilterOutConnectedComponents(rightWebCamOriginalImage);
                
                leftWebCamOriginalImage.UnLock();
                rightWebCamOriginalImage.UnLock();

                leftWebCamProcessing.UnLock();
                rightWebCamProcessing.UnLock();

                this.CurrentState = 5;
            }
            else if (CurrentState == 5)
            {
                bool faceInCurrentFrame = leftWebCamProcessing.ConnectedRegionsExist() || rightWebCamProcessing.ConnectedRegionsExist();

                if (faceInCurrentFrame && !faceDetectedPreviously)
                {
                    lock (this)
                    {
                        this.leftWebCamProcessedImage = leftWebCamOriginalImage;
                        this.rightWebCamProcessedImage = rightWebCamOriginalImage;
                    }
                    this.CurrentState = 6;
                }
                else if (faceInCurrentFrame && faceDetectedPreviously)
                {
                    lock (this)
                    {
                        this.leftWebCamProcessedImage = leftWebCamOriginalImage;
                        this.rightWebCamProcessedImage = rightWebCamOriginalImage;
                    }
                    this.CurrentState = 1;
                }
                else
                {
                    lock (this)
                    {
                        this.leftWebCamProcessedImage = leftWebCamOriginalImage;
                        this.rightWebCamProcessedImage = rightWebCamOriginalImage;
                    }
                    this.CurrentState = 0;
                }                
            }
            else if (CurrentState == 6)
            {
                this.faceDetectedPreviously = true;
                Robot.Instance.Brain.TextToSpeech.Utility = 1;
                this.CurrentState = 1;
            }
        }
        #endregion

        #region Properties
        public Bitmap LeftWebCamProcessedImage
        {
            get
            {
                if (this.leftWebCamProcessing != null)
                {
                    return new Bitmap(leftWebCamProcessedImage.ProcessedBitmap);
                }
                else
                {
                    return new Bitmap(320, 240);
                }
            }
        }

        public Bitmap RightWebCamProcessedImage
        {
           get 
           {
               if (this.rightWebCamProcessing != null)
               {
                   return new Bitmap(rightWebCamProcessedImage.ProcessedBitmap);
               }
               else
               {
                   return new Bitmap(320, 240);
               }
           }
        }

        public bool FaceDetected
        {
            get { return this.faceDetectedPreviously; }
        }

        #endregion


    }
}
